﻿using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Single.Npoi
{
    public class NpoiFile<T> where T : class, new()
    {
        private readonly string path;
        private readonly int sheetIndex;

        public NpoiFile(string path, int sheetIndex = 0)
        {
            this.path = path;
            this.sheetIndex = sheetIndex;
        }

        public DataTable ToDataTable()
        {
            return NpoiHelper.ExcelToDataTable(path, "sheet1", sheetIndex);
        }

        public List<T> ToList<T2>(NpoiMap<T2> maps)
        {
            var list = new List<T>();

            var dt = NpoiHelper.ExcelToDataTable(path, "sheet1", sheetIndex);

            int rowIndex = 1;

            Type type = typeof(T2);

            foreach (DataRow row in dt.Rows)
            {
                T item = new T();

                foreach (var map in maps.Values)
                {
                    object value = null;

                    if (dt.Columns.Contains(map.Key))
                    {
                        var prop = map.Property;

                        if (prop != null)
                        {
                            value = row[map.Key];

                            if (value != null)
                            {
                                try
                                {
                                    if (map.MemberExpr.Expression.Type != type)
                                    {
                                        var temp = map.MemberExpr?.ToString();

                                        var tempList = temp.Split('.').ToList();

                                        var navPi = type.GetProperty(tempList[1]);

                                        var navEntity = navPi.GetValue(item);

                                        if (navEntity == null)
                                            navPi.SetValue(item, Activator.CreateInstance(map.MemberExpr.Expression.Type));

                                        navEntity = navPi.GetValue(item);

                                        prop.SetValue(navEntity, Convert.ChangeType(value, prop.PropertyType));
                                    }
                                    else
                                    {
                                        prop.SetValue(item, Convert.ChangeType(value, prop.PropertyType));
                                    }
                                }
                                catch { }
                            }
                        }
                    }

                    if (map.IsRequired && (value == null || string.IsNullOrEmpty(value.ToString())))
                    {
                        throw new Exception($"第【{rowIndex}】行数据【{map.Key}】列，未填写内容");
                    }
                }

                list.Add(item); rowIndex++;
            }

            return list;
        }
    }
}